package com.app.yourradioapp593.services;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.PowerManager;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.app.yourradioapp593.BuildConfig;
import com.app.yourradioapp593.Config;
import com.app.yourradioapp593.R;
import com.app.yourradioapp593.activities.MainActivity;
import com.app.yourradioapp593.callbacks.CallbackAlbumArt;
import com.app.yourradioapp593.database.prefs.SharedPref;
import com.app.yourradioapp593.metadata.IcyHttpDataSourceFactory;
import com.app.yourradioapp593.models.AlbumArt;
import com.app.yourradioapp593.models.Radio;
import com.app.yourradioapp593.rests.RestAdapter;
import com.app.yourradioapp593.services.parser.URLParser;
import com.app.yourradioapp593.utils.AsyncTaskExecutor;
import com.app.yourradioapp593.utils.Constant;
import com.app.yourradioapp593.utils.HttpsTrustManager;
import com.app.yourradioapp593.utils.Tools;
import com.solodroid.android.exoplayer2.ExoPlaybackException;
import com.solodroid.android.exoplayer2.ExoPlayerFactory;
import com.solodroid.android.exoplayer2.PlaybackParameters;
import com.solodroid.android.exoplayer2.Player;
import com.solodroid.android.exoplayer2.Timeline;
import com.solodroid.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.solodroid.android.exoplayer2.source.ExtractorMediaSource;
import com.solodroid.android.exoplayer2.source.MediaSource;
import com.solodroid.android.exoplayer2.source.TrackGroupArray;
import com.solodroid.android.exoplayer2.source.hls.DefaultHlsExtractorFactory;
import com.solodroid.android.exoplayer2.source.hls.HlsMediaSource;
import com.solodroid.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.solodroid.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.solodroid.android.exoplayer2.trackselection.TrackSelectionArray;
import com.solodroid.android.exoplayer2.upstream.AssetDataSource;
import com.solodroid.android.exoplayer2.upstream.DataSpec;
import com.solodroid.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.solodroid.android.exoplayer2.upstream.DefaultDataSourceFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

@SuppressLint("StaticFieldLeak")
@SuppressWarnings("deprecation")
public class RadioPlayerService extends Service implements AudioFocusChangedCallback {

    public static final String TAG = "RadioService";
    private MediaSessionCompat mediaSessionCompat;
    MediaControllerCompat mediaControllerCompat;
    private PlaybackStateCompat.Builder stateBuilder;
    private MediaSessionCompat.Callback callback;
    Call<CallbackAlbumArt> callbackCall = null;
    LoadSong loadSong;
    PlaybackStateCompat playbackState;
    NotificationCompat.Builder builder;
    static NotificationManager notificationManager;
    private BroadcastReceiver broadcastReceiver;
    static SharedPref sharedPref;
    Bitmap bitmap;
    private Boolean isCanceled = false;
    boolean isCounterRunning = false;
    static RadioPlayerService service;
    static Context context;
    static Radio radio;
    ComponentName componentName;
    AudioManager mAudioManager;
    PowerManager.WakeLock mWakeLock;
    private static final int NOTIFICATION_ID = 1;
    private static final String NOTIFICATION_CHANNEL_ID = BuildConfig.APPLICATION_ID;
    public static final String ACTION_TOGGLE = BuildConfig.APPLICATION_ID + ".togglepause";
    public static final String ACTION_PLAY = BuildConfig.APPLICATION_ID + ".play";
    public static final String ACTION_NEXT = BuildConfig.APPLICATION_ID + ".next";
    public static final String ACTION_PREVIOUS = BuildConfig.APPLICATION_ID + ".prev";
    public static final String ACTION_STOP = BuildConfig.APPLICATION_ID + ".stop";

    public static final String MEDIA_SESSION_TAG = "MEDIA_SESSION";

    static public void initialize(Context context) {
        RadioPlayerService.context = context;
        RadioPlayerService.sharedPref = new SharedPref(context);
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    public void initializeRadio(Context context, Radio station) {
        RadioPlayerService.context = context;
        RadioPlayerService.sharedPref = new SharedPref(context);
        radio = station;
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    public static RadioPlayerService getInstance() {
        return service;
    }

    public static RadioPlayerService createInstance() {
        if (service == null) {
            service = new RadioPlayerService();
        }
        return service;
    }

    public Boolean isPlaying() {
        if (service == null) {
            return false;
        } else {
            if (Constant.exoPlayer != null) {
                return Constant.exoPlayer.getPlayWhenReady();
            } else {
                return false;
            }
        }
    }

    @SuppressLint({"UnspecifiedImmutableFlag", "UnspecifiedRegisterReceiverFlag"})
    @Override
    public void onCreate() {
        super.onCreate();

        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (mAudioManager != null) {
            mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        }

        componentName = new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName());
        mAudioManager.registerMediaButtonEventReceiver(componentName);

        LocalBroadcastManager.getInstance(this).registerReceiver(onCallIncome, new IntentFilter("android.intent.action.PHONE_STATE"));
        LocalBroadcastManager.getInstance(this).registerReceiver(onHeadPhoneDetect, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));

        DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        AdaptiveTrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        DefaultTrackSelector trackSelector = new DefaultTrackSelector(trackSelectionFactory);
        Constant.exoPlayer = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), trackSelector);
        Constant.exoPlayer.addListener(eventListener);

        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
        mWakeLock.setReferenceCounted(false);

        stateBuilder = new PlaybackStateCompat.Builder();

        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                handleCommand(intent);
            }
        };

        MediaControllerCompat.Callback controllerCallback = new MediaControllerCompat.Callback() {
            @Override
            public void onPlaybackStateChanged(PlaybackStateCompat state) {
                if (state.getState() == PlaybackStateCompat.STATE_PAUSED || state.getState() == PlaybackStateCompat.STATE_PLAYING) {
                    if (builder != null) {
                        notificationManager.notify(NOTIFICATION_ID, builder.build());
                    }
                }
                if (state.getState() == PlaybackStateCompat.STATE_PAUSED) {
                    Log.d(TAG, "MediaControllerCompat state paused");
                } else if (state.getState() == PlaybackStateCompat.STATE_PLAYING) {
                    if (builder != null) {
                        startForeground(NOTIFICATION_ID, builder.build());
                        Log.d(TAG, "MediaControllerCompat state playing");
                    }
                }
            }

            @Override
            public void onMetadataChanged(MediaMetadataCompat metadata) {
                if (builder != null) {
                    notificationManager.notify(NOTIFICATION_ID, builder.build());
                }
            }
        };

        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_PREVIOUS);
        filter.addAction(ACTION_TOGGLE);
        filter.addAction(ACTION_NEXT);
        filter.addAction(ACTION_STOP);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            this.registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED);
        } else {
            this.registerReceiver(broadcastReceiver, filter);
        }

        callback = new MediaSessionCompat.Callback() {
            @Override
            public void onPlay() {
                mediaSessionCompat.setActive(true);
                newPlay();
            }

            @Override
            public void onPause() {
                togglePlayPause();
                if (Constant.exoPlayer.getPlayWhenReady()) {
                    mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_PAUSED));
                } else {
                    mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_PLAYING));
                }
            }

            @Override
            public void onSkipToNext() {
                next();
                mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_SKIPPING_TO_NEXT));
            }

            @Override
            public void onSkipToPrevious() {
                previous();
                mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_SKIPPING_TO_PREVIOUS));
            }

            @Override
            public void onStop() {
                mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_STOPPED));
                mediaSessionCompat.setActive(false);
                stop(false);
            }

            @Override
            public void onSkipToQueueItem(long id) {
                mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM));
                onPlay();
            }

            @Override
            public void onSeekTo(long pos) {
                mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_BUFFERING));
            }

            @Override
            public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
                KeyEvent mediaEvent = mediaButtonEvent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
                if (mediaEvent.getAction() == KeyEvent.ACTION_UP) {
                    int keyCode = mediaEvent.getKeyCode();
                    switch (keyCode) {
                        case KeyEvent.KEYCODE_MEDIA_NEXT:
                            onSkipToNext();
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                            onSkipToPrevious();
                            break;
                        case KeyEvent.KEYCODE_MEDIA_PLAY:
                        case KeyEvent.KEYCODE_MEDIA_PAUSE:
                            onPause();
                            break;
                        case KeyEvent.KEYCODE_MEDIA_STOP:
                            if (isPlaying()) {
                                new Handler(Looper.getMainLooper()).postDelayed(() -> stop(false), 2000);
                                pause();
                            } else {
                                stop(false);
                            }
                            break;
                    }
                }
                return true;
            }
        };

        mediaSessionCompat = new MediaSessionCompat(this, MEDIA_SESSION_TAG);

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            mediaSessionCompat.setCallback(callback);
            mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_NONE));
            mediaControllerCompat = new MediaControllerCompat(this, mediaSessionCompat);
            mediaControllerCompat.registerCallback(controllerCallback);
        }

    }

    @Override
    public void onTaskRemoved(Intent intent) {
        super.onTaskRemoved(intent);
        if (isPlaying()) {
            new Handler(Looper.getMainLooper()).postDelayed(() -> {
                ((MainActivity) context).finish();
                stop(false);
            }, 2000);
            pause();
        } else {
            ((MainActivity) context).finish();
            stop(false);
        }
        Constant.isRadioPlaying = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        String action = intent.getAction();
        if (action != null)
            try {
                handleCommand(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }
        return START_NOT_STICKY;
    }

    /** @noinspection SwitchStatementWithoutDefaultBranch*/
    private void handleCommand(Intent intent) {
        String action = intent.getAction();
        switch (action) {
            case ACTION_TOGGLE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    togglePlayPause();
                } else {
                    callback.onPause();
                }
                break;
            case ACTION_NEXT:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    next();
                } else {
                    callback.onSkipToNext();
                }
                break;
            case ACTION_PREVIOUS:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    previous();
                } else {
                    callback.onSkipToPrevious();
                }
                break;
            case ACTION_PLAY:
                newPlay();
                break;
            case ACTION_STOP:
                if (isPlaying()) {
                    new Handler(Looper.getMainLooper()).postDelayed(() -> callback.onStop(), 2000);
                    pause();
                } else {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                        stop(false);
                    } else {
                        callback.onStop();
                    }
                }
                break;
        }
    }

    Player.EventListener eventListener = new Player.EventListener() {
        @Override
        public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) {

        }

        @Override
        public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

        }

        @Override
        public void onLoadingChanged(boolean isLoading) {

        }

        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            if (playbackState == Player.STATE_ENDED) {
                next();
            }
            if (playbackState == Player.STATE_READY && playWhenReady) {
                if (!isCanceled) {
                    ((MainActivity) context).seekBarUpdate();
                    ((MainActivity) context).setBuffer(false);
                    if (builder == null) {
                        createNotification();
                    } else {
                        notificationManager.notify(NOTIFICATION_ID, builder.build());
                        updateNotificationPlay(Constant.exoPlayer.getPlayWhenReady());
                    }

                    updateNotificationAlbumArt(sharedPref.getBaseUrl() + "/upload/" + Constant.item_radio.get(Constant.position).radio_image);

                    updateNotificationMetadata(Constant.item_radio.get(Constant.position).category_name);

                    changePlayPause(true);

                    if (Config.ENABLE_RADIO_TIMEOUT) {
                        if (isCounterRunning) {
                            mCountDownTimer.cancel();
                        }
                    }

                } else {
                    isCanceled = false;
                    stopExoPlayer();
                }
            }
            if (playWhenReady) {
                if (!mWakeLock.isHeld()) {
                    mWakeLock.acquire(60000);
                }
            } else {
                if (mWakeLock.isHeld()) {
                    mWakeLock.release();
                }
            }
        }

        @Override
        public void onRepeatModeChanged(int repeatMode) {

        }

        @Override
        public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {

        }

        @Override
        public void onPlayerError(ExoPlaybackException error) {
            stop(true);
            if (Config.ENABLE_RADIO_TIMEOUT) {
                if (isCounterRunning) {
                    mCountDownTimer.cancel();
                }
            }
        }

        @Override
        public void onPositionDiscontinuity(int reason) {

        }

        @Override
        public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

        }

        @Override
        public void onSeekProcessed() {

        }
    };

    private void changePlayPause(Boolean play) {
        ((MainActivity) context).changePlayPause(play);
    }

    private void togglePlayPause() {
        if (Constant.exoPlayer.getPlayWhenReady()) {
            pause();
            updateNotificationAlbumArt("");
            updateNotificationMetadata(Constant.item_radio.get(Constant.position).category_name);
        } else {
            if (Tools.isConnect(context)) {
                if (Constant.item_radio.get(Constant.position).radio_type.equals("mp3")) {
                    play();
                } else {
                    newPlay();
                }
            } else {
                Toast.makeText(context, getString(R.string.internet_not_connected), Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void play() {
        new Handler().postDelayed(() -> {
            Constant.exoPlayer.setPlayWhenReady(true);
            Constant.exoPlayer.seekTo(Constant.exoPlayer.getCurrentWindowIndex(), Constant.exoPlayer.getCurrentPosition());
            changePlayPause(true);
            //updateSelectedItemPosition(true);
            updateNotificationPlay(Constant.exoPlayer.getPlayWhenReady());
            ((MainActivity) context).seekBarUpdate();
            //Constant.showEqualizerView = true;
        }, 100);
    }

    private void pause() {
        new Handler().postDelayed(() -> {
            Constant.exoPlayer.setPlayWhenReady(false);
            changePlayPause(false);
            //updateSelectedItemPosition(false);
            updateNotificationPlay(Constant.exoPlayer.getPlayWhenReady());
            //Constant.showEqualizerView = false;
        }, 100);
    }

    private void next() {
        if (Constant.item_radio != null && Constant.item_radio.size() > 0) {
            RadioPlayerService.createInstance().initializeRadio(context, Constant.item_radio.get(Constant.position));
            Tools.getPosition(true);
            radio = Constant.item_radio.get(Constant.position);
            //updateSelectedItemPosition(true);
            newPlay();
            ((MainActivity) context).hideSeekBar();
            ((MainActivity) context).updatePlayerView(
                    Constant.item_radio.get(Constant.position).radio_name,
                    Constant.item_radio.get(Constant.position).category_name,
                    sharedPref.getBaseUrl() + "/upload/" + Constant.item_radio.get(Constant.position).radio_image
            );
            //Constant.showEqualizerView = true;
        }
    }

    private void previous() {
        if (Constant.item_radio != null && Constant.item_radio.size() > 0) {
            RadioPlayerService.createInstance().initializeRadio(context, Constant.item_radio.get(Constant.position));
            Tools.getPosition(false);
            radio = Constant.item_radio.get(Constant.position);
            //updateSelectedItemPosition(true);
            newPlay();
            ((MainActivity) context).hideSeekBar();
            ((MainActivity) context).updatePlayerView(
                    Constant.item_radio.get(Constant.position).radio_name,
                    Constant.item_radio.get(Constant.position).category_name,
                    sharedPref.getBaseUrl() + "/upload/" + Constant.item_radio.get(Constant.position).radio_image
            );
            //Constant.showEqualizerView = true;
        }
    }

    private void newPlay() {
        Tools.postDelayed(() -> {
            //Constant.showEqualizerView = true;
            loadSong = new LoadSong();
            loadSong.execute();
            if (Config.ENABLE_RADIO_TIMEOUT) {
                if (isCounterRunning) {
                    mCountDownTimer.cancel();
                }
                mCountDownTimer.start();
            }
        }, 100);
    }

    public class LoadSong extends AsyncTaskExecutor<Void, Void, Void> {

        MediaSource mediaSource;

        @Override
        protected void onPreExecute() {
            ((MainActivity) context).setBuffer(true);
            ((MainActivity) context).changeSongName(Constant.item_radio.get(Constant.position).category_name);
            updateNotificationMetadata(Constant.item_radio.get(Constant.position).category_name);
            onMediaMetadataCompatChanged(Constant.item_radio.get(Constant.position).category_name);
            updateNotificationAlbumArt(sharedPref.getBaseUrl() + "/upload/" + Constant.item_radio.get(Constant.position).radio_image);
        }

        @Override
        protected Void doInBackground(Void params) {
            try {
                HttpsTrustManager.allowAllSSL();
                String url = Constant.item_radio.get(Constant.position).radio_url;
                String type = Constant.item_radio.get(Constant.position).radio_type;

                if (type.equals("mp3")) {
                    Constant.radio_type = false;
                } else {
                    Constant.radio_type = true;
                }
                //Constant.radio_type = !type.equals("mp3");

                DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(), null, icy);
                if (url.startsWith("http") || url.startsWith("https")) {
                    if (url.contains(".m3u8") || url.contains(".M3U8")) {
                        mediaSource = new HlsMediaSource.Factory(dataSourceFactory)
                                .setAllowChunklessPreparation(false)
                                .setExtractorFactory(new DefaultHlsExtractorFactory())
                                .createMediaSource(Uri.parse(url));
                    } else if (url.contains(".m3u") || url.contains("yp.shoutcast.com/sbin/tunein-station.m3u?id=")) {
                        url = URLParser.getUrl(url);
                        mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                                .setExtractorsFactory(new DefaultExtractorsFactory())
                                .createMediaSource(Uri.parse(url));
                    } else if (url.contains(".pls") || url.contains("listen.pls?sid=") || url.contains("yp.shoutcast.com/sbin/tunein-station.pls?id=")) {
                        url = URLParser.getUrl(url);
                        mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                                .setExtractorsFactory(new DefaultExtractorsFactory())
                                .createMediaSource(Uri.parse(url));
                    } else {
                        mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                                .setExtractorsFactory(new DefaultExtractorsFactory())
                                .createMediaSource(Uri.parse(url));
                    }
                    Log.d(TAG, "from url");
                } else {
                    AssetDataSource assetDataSource = new AssetDataSource(context);
                    DataSpec dataSpec = new DataSpec(Uri.parse("asset:///" + url));
                    assetDataSource.open(dataSpec);
                    mediaSource = new ExtractorMediaSource.Factory(() -> assetDataSource).createMediaSource(dataSpec.uri);
                    Log.d(TAG, "from assets");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            return params;
        }

        @Override
        protected void onPostExecute(Void result) {
            if (context != null) {
                Constant.exoPlayer.seekTo(Constant.exoPlayer.getCurrentWindowIndex(), Constant.exoPlayer.getCurrentPosition());
                Constant.exoPlayer.prepare(mediaSource, true, true);
                Constant.exoPlayer.setPlayWhenReady(true);
                updateView();
            }
        }

    }

    private void updateView() {
        if (Constant.item_radio != null && Constant.item_radio.size() > 0) {
            String radioId = Constant.item_radio.get(Constant.position).radio_id;
            if (!radioId.equals(Constant.CURRENT_ID)) {
                ((MainActivity) context).updateView(radioId);
                Constant.CURRENT_ID = radioId;
            }
        }
    }

    CountDownTimer mCountDownTimer = new CountDownTimer(Config.RADIO_TIMEOUT_CONNECTION, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            isCounterRunning = true;
            Log.d(TAG, "seconds remaining: " + millisUntilFinished / 1000);
        }

        @Override
        public void onFinish() {
            isCounterRunning = false;
            if (Constant.progressVisibility) {
                stop(true);
            }
        }
    };

    private void stop(boolean showMessage) {
        if (Constant.exoPlayer != null) {
            try {
                mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
                LocalBroadcastManager.getInstance(this).unregisterReceiver(onCallIncome);
                LocalBroadcastManager.getInstance(this).unregisterReceiver(onHeadPhoneDetect);
                mAudioManager.unregisterMediaButtonEventReceiver(componentName);
            } catch (Exception e) {
                e.printStackTrace();
            }
            changePlayPause(false);
            stopExoPlayer();
            service = null;
            stopForeground(true);
            stopSelf();
            ((MainActivity) context).setBuffer(false);
            ((MainActivity) context).changePlayPause(false);
            //updateSelectedItemPosition(false);
            //Constant.showEqualizerView = false;
            if (showMessage) {
                Toast.makeText(context, getString(R.string.error_loading_radio), Toast.LENGTH_SHORT).show();
            }
        }
    }

    public void stopExoPlayer() {
        if (Constant.exoPlayer != null) {
            Constant.exoPlayer.stop();
        }
    }

    private PlaybackStateCompat createPlaybackState(int state) {
        long playbackPos = 0;
        playbackState = stateBuilder.setState(state, playbackPos, 1.0f).build();
        return playbackState;
    }

    @Override
    public void onFocusGained() {
        mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_PLAYING));
    }

    @Override
    public void onFocusLost() {
        mediaSessionCompat.setPlaybackState(createPlaybackState(PlaybackStateCompat.STATE_PAUSED));
    }

    public IcyHttpDataSourceFactory icy = new IcyHttpDataSourceFactory
            .Builder(Tools.getUserAgent())
            .setAllowCrossProtocolRedirects(true)
            .setConnectTimeoutMillis(1000)
            .setIcyHeadersListener(icyHeaders -> {
            })
            .setIcyMetadataChangeListener(icyMetadata -> {
                try {
                    if (Config.DISPLAY_SONG_METADATA) {
                        Tools.postDelayed(() -> {
                            if ("".equalsIgnoreCase(icyMetadata.getStreamTitle())) {
                                updateNotificationMetadata(Constant.item_radio.get(Constant.position).category_name);
                                onMediaMetadataCompatChanged(Constant.item_radio.get(Constant.position).category_name);
                            } else {
                                updateNotificationMetadata(icyMetadata.getStreamTitle());
                                onMediaMetadataCompatChanged(icyMetadata.getStreamTitle());
                                requestAlbumArt(icyMetadata.getStreamTitle());
                            }
                        }, 1000);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).build();

    private void onMediaMetadataCompatChanged(String metadata) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (mediaSessionCompat != null) {
                mediaSessionCompat.setMetadata(new MediaMetadataCompat.Builder()
                        .putString(MediaMetadataCompat.METADATA_KEY_TITLE, Constant.item_radio.get(Constant.position).radio_name)
                        .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, metadata)
                        .build());
            }
        }
    }

    private void requestAlbumArt(String title) {
        if (Config.DISPLAY_ALBUM_ART_METADATA) {
            callbackCall = RestAdapter.createAlbumArtAPI().getAlbumArt(title, "music", 1);
            callbackCall.enqueue(new Callback<CallbackAlbumArt>() {
                public void onResponse(@NonNull Call<CallbackAlbumArt> call, @NonNull Response<CallbackAlbumArt> response) {
                    CallbackAlbumArt resp = response.body();
                    if (resp != null && resp.resultCount != 0) {
                        ArrayList<AlbumArt> albumArts = resp.results;
                        String artWorkUrl = albumArts.get(0).artworkUrl100.replace("100x100bb", "300x300bb");
                        ((MainActivity) context).changeAlbumArt(artWorkUrl);
                        updateNotificationAlbumArt(artWorkUrl);
                        Tools.postDelayed(() -> ((MainActivity) context).showImageAlbumArt(true), 100);
                        Log.d(TAG, "request album art success");
                    } else {
                        ((MainActivity) context).changeAlbumArt("");
                        updateNotificationAlbumArt("");
                        Tools.postDelayed(() -> ((MainActivity) context).showImageAlbumArt(false), 100);
                        Log.d(TAG, "request album art failed");
                    }
                }

                public void onFailure(@NonNull Call<CallbackAlbumArt> call, @NonNull Throwable th) {
                    Log.d(TAG, "onFailure");
                }
            });
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

    public Radio getPlayingRadioStation() {
        return radio;
    }

    private void getBitmapFromURL(String src) {
        try {
            URL url = new URL(src.replace(" ", "%20"));
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            bitmap = BitmapFactory.decodeStream(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    BroadcastReceiver onCallIncome = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            if (isPlaying()) {
                if (state != null) {
                    if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK) || state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
                        Intent intent_stop = new Intent(context, RadioPlayerService.class);
                        intent_stop.setAction(ACTION_TOGGLE);
                        startService(intent_stop);
                        Toast.makeText(context, "there is an call!!", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(context, "whoops!!", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    };

    BroadcastReceiver onHeadPhoneDetect = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Constant.is_playing) {
                togglePlayPause();
            }
        }
    };

    AudioManager.OnAudioFocusChangeListener onAudioFocusChangeListener = focusChange -> {
        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                if (Config.RESUME_RADIO_ON_PHONE_CALL && Constant.isRadioPlaying) {
                    togglePlayPause();
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS:
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                if (isPlaying()) {
                    togglePlayPause();
                    Constant.isRadioPlaying = true;
                } else {
                    Constant.isRadioPlaying = false;
                }
                break;
        }
    };

    @SuppressWarnings("UnusedReturnValue")
    private boolean createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, getString(R.string.app_name), NotificationManager.IMPORTANCE_LOW);
            channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);
            return true;
        }
        return false;
    }

    private void createNotification() {
        createNotificationChannel();
        buildNotification();
    }

    private void updateNotificationAlbumArt(String artWorkUrl) {
        new AsyncTaskExecutor<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void params) {
                try {
                    if (artWorkUrl.equals("")) {
                        getBitmapFromURL(sharedPref.getBaseUrl() + "/upload/" + Constant.item_radio.get(Constant.position).radio_image.replace(" ", "%20"));
                    } else {
                        getBitmapFromURL(artWorkUrl);
                    }

                    if (builder != null) {
                        builder.setLargeIcon(bitmap);
                        notificationManager.notify(NOTIFICATION_ID, builder.build());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return params;
            }

            @Override
            protected void onPostExecute(Void result) {

            }
        }.execute();
    }

    private void updateNotificationMetadata(String title) {
        if (builder != null) {
            ((MainActivity) context).changeSongName(title);
            builder.setContentTitle(Constant.item_radio.get(Constant.position).radio_name);
            builder.setContentText(title);
            notificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    @SuppressLint("InlinedApi")
    private void buildNotification() {

        Intent notificationIntent = new Intent(this, MainActivity.class);
        notificationIntent.setAction(Intent.ACTION_MAIN);
        notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);

        String title = Constant.item_radio.get(Constant.position).radio_name;
        String artist = Constant.item_radio.get(Constant.position).category_name;

        builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        builder.setContentIntent(pendingIntent)
                .setLargeIcon(Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.ic_thumbnail), 128, 128, false))
                .setTicker(title)
                .setSmallIcon(R.drawable.ic_radio_notif)
                .setContentTitle(title)
                .setContentText(artist)
                .setPriority(Notification.PRIORITY_LOW)
                .setWhen(0)
                .setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
                        .setMediaSession(mediaSessionCompat.getSessionToken())
                        .setShowCancelButton(true)
                        .setShowActionsInCompactView(0, 1, 2))
                .setVisibility(NotificationCompat.VISIBILITY_PRIVATE)
                .addAction(R.drawable.ic_action_previous, "previous", getPlaybackAction(ACTION_PREVIOUS))
                .addAction(R.drawable.ic_action_pause, "pause", getPlaybackAction(ACTION_TOGGLE))
                .addAction(R.drawable.ic_action_next, "next", getPlaybackAction(ACTION_NEXT))
                .addAction(R.drawable.ic_action_close, "close", getPlaybackAction(ACTION_STOP));

        startForeground(NOTIFICATION_ID, builder.build());
    }

    @SuppressLint("RestrictedApi")
    private void updateNotificationPlay(Boolean isPlay) {
        if (builder != null) {
            builder.mActions.remove(1);
            Intent playIntent = new Intent(getApplicationContext(), RadioPlayerService.class);
            playIntent.setAction(ACTION_TOGGLE);
            if (isPlay) {
                builder.mActions.add(1, new NotificationCompat.Action(R.drawable.ic_action_pause, "pause", getPlaybackAction(ACTION_TOGGLE)));
            } else {
                builder.mActions.add(1, new NotificationCompat.Action(R.drawable.ic_action_play, "Play", getPlaybackAction(ACTION_TOGGLE)));
            }
            notificationManager.notify(NOTIFICATION_ID, builder.build());
        }
    }

    @SuppressLint("InlinedApi")
    private PendingIntent getPlaybackAction(String action) {
        Intent intent = new Intent();
        intent.setAction(action);
        return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
    }

    @Override
    public void onDestroy() {
        try {
            mediaSessionCompat.release();
            unregisterReceiver(broadcastReceiver);

            Constant.exoPlayer.stop();
            Constant.exoPlayer.release();
            Constant.exoPlayer.removeListener(eventListener);
            if (mWakeLock.isHeld()) {
                mWakeLock.release();
            }
            try {
                mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
                LocalBroadcastManager.getInstance(this).unregisterReceiver(onCallIncome);
                LocalBroadcastManager.getInstance(this).unregisterReceiver(onHeadPhoneDetect);
                mAudioManager.unregisterMediaButtonEventReceiver(componentName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }

}
